package main

//一个融合了并发、缓冲、退出通知等多重特性的生成器

import (
	"fmt"
	"math/rand"
)

// done接收通知退出信号
func GenerateIntA(done chan struct{}) chan int {
	ch := make(chan int, 5)

	go func() {
	Lable:
		for {
			select {
			case ch <- rand.Int():
			case <-done:
				break Lable
			}
		}
		close(ch)
	}()

	return ch
}

// done接收退出通知信号
func GenerateIntB(done chan struct{}) chan int {
	ch := make(chan int, 10)

	go func() {
	Lable:
		for {
			select {
			case ch <- rand.Int():
			case <-done:
				break Lable
			}
		}
		close(ch)
	}()

	return ch
}

// 通过select执行输入（Fan in）操作
func GenerateInt(done chan struct{}) chan int {
	ch := make(chan int, 10)
	send := make(chan struct{})

	go func() {
	Lable:
		for {
			select {
			case ch <- <-GenerateIntA(send):
			case ch <- <-GenerateIntB(send):
			case <-done:
				send <- struct{}{}
				send <- struct{}{}
				break Lable
			}
		}
		close(ch)
	}()
	return ch
}

func main() {
	done := make(chan struct{}) //创建一个作为接收退出信号的 chan

	ch := GenerateInt(done) //启动生成器

	for i := 0; i < 10; i++ {
		fmt.Println(<-ch)
	}

	done <- struct{}{} //通知生产者停止生产
	fmt.Println("stop generate")
}
